﻿#ifndef ZDBConnectionPool_H
#define ZDBConnectionPool_H

/*******************************************************************************
** 线程安全数据库连接池，每个线程获取自己的数据库连接，使用完后回收，供其他线程使用。
** 每个数据库对应一个线程池。
**
*******************************************************************************/
#include <QObject>
#include <QSqlDatabase>
#include <QMutex>
#include <QMap>

#include "ZFCommonHeader.h"

ZFLIB_BEGIN_NAMESPACE

// 数据库连接配置
struct DBConnectionConfig
{
    QString db_type; /* 数据库类型，如MYSQL,SQLITE */
    QString hostname; /* 主机名/ip地址 */
    QString username; /* 用户名 */
    QString password; /* 密码 */
    int port; /* 端口号 */
};

class ZFLIB_API ZDBConnectionPool : public QObject
{
public:
    ZDBConnectionPool(const DBConnectionConfig &config,
                      QObject *parent = NULL);
    ~ZDBConnectionPool();

    /**
     * @brief getThreadDBConnection
     *  获取数据库连接，因为Qt的数据库连接不能跨线程使用，所以每个运行线程必须
     *  申请各自的数据库连接。调用此函数可以申请一个线程专用连接。
     *  不要从其他地方获取数据库连接，只能从此获取。
     * @return
     *  线程专用数据库连接
     */
    QSqlDatabase getThreadDBConnection();

    /**
     * @brief releaseConnection
     *  释放此线程使用的数据库连接，回收以供其他线程使用
     */
    void releaseConnection();

private:
    /**
     * @brief createConnection
     *  创建数据库连接
     * @return
     */
    QSqlDatabase createNewConnection();

    /**
     * @brief allocConnection
     *  分配一个数据库连接，根据情况从空闲队列中取，或重新创建。
     * @return
     */
    QSqlDatabase allocConnection();

private:
    // 互斥锁
    QMutex m_mutex;

    // 数据库连接配置
    DBConnectionConfig m_db_config;

    // 繁忙连接池
    QMap<qint64, QSqlDatabase> m_busy_connections;

    // 空闲连接池
    QList<QSqlDatabase> m_idle_connection;
};

ZFLIB_END_NAMESPACE

#endif // ZDBConnectionPool_H
